﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections;
using System.IO;
using System.Threading;
using Microsoft.VisualBasic;

namespace ImagesBatchDownloading
{
    public partial class ImageForm : Form
    {
        //一次自动编号(图片重命名用)
        private static int fileIndex = 1;

        public object slock = new object();

        //private static ManualResetEvent allDone = new ManualResetEvent(false);

        #region 属性

        //是否下载页面内包含CSS文件内的图片
        private bool _IsInclueCssImages = false;

        //目录
        private string dir = string.Empty;

        //图片是否重命名
        private bool _IsRename = false;

        //CSS正则表达式备份
        private static readonly string CssPattern_BAK = @"[\w.:/]*((\.css){1})";
        private string _CssPattern = CssPattern_BAK;
        /// <summary>
        /// 匹配CSS正则表达式
        /// </summary>
        public string CssPattern
        {
            get { return _CssPattern; }
            set { _CssPattern = value; }
        }

        //请求超时时间备份
        private static readonly int Timeout_BAK = 0x2710;  //30秒 0x7530 20秒 0x4E20 10秒 0x2710
        private int _Timeout = Timeout_BAK;
        /// <summary>
        /// 设置请求超时时间
        /// </summary>
        public int Timeout
        {
            get { return _Timeout; }
            set { _Timeout = value; }
        }

        //域名正则表达式备份
        private static readonly string DomainPattern_BAK = @"^((http(s)?://)?)+[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?";
        private string _DomainPattern = DomainPattern_BAK;
        /// <summary>
        /// 匹配域名正则表达式
        ///     "^((http(s)?://)?)+[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?"
        /// </summary>
        public string DomainPattern
        {
            get { return _DomainPattern; }
            set { _DomainPattern = value; }
        }

        //图片链接的正则表达式备份
        private static readonly string ImagePattern_BAK = @"((http(s)?://)?)+(((/?)+[\w-.]+(/))*)+[\w-./]+\.+(jpg|jpeg|png|ico|bmp|gif)";
        private string _ImagePattern = ImagePattern_BAK;
        /// <summary>
        /// 匹配图片链接的正则表达式
        ///     "((http(s)?://)?)+(((/?)+[\w-.]+(/))*)+[\w-./]+\.+(jpg|jpeg|png|ico|bmp|gif)"
        /// </summary>
        public string ImagePattern
        {
            get { return _ImagePattern; }
            set { _ImagePattern = value; }
        }

        //限制下载文件大小备份
        private static readonly long FileSize_BAK = 1024L * 1024L;      //1M
        private long _FileSize = FileSize_BAK;
        /// <summary>
        /// 文件大小(KB) 此处转换为字节
        /// </summary>
        public long FileSize
        {
            get { return _FileSize; }
            set { _FileSize = value; }
        }

        //网址匹配正则表达式备份
        private static readonly string URL_BAK = @"^http(s)?://+([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
        private string _URL = URL_BAK;
        /// <summary>
        /// 设置网址匹配正则表达式
        ///     "^http(s)?://+([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?"
        /// </summary>
        public string URL
        {
            get { return _URL; }
            set { _URL = value; }
        }



        #endregion

        public ImageForm()
        {
            InitializeComponent();
        }

        [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
        static extern bool QueryPerformanceCounter(ref long count);

        [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
        static extern bool QueryPerformanceFrequency(ref long count);


        /// <summary>
        /// 根据网址分析并下载
        /// 搜索规则：
        ///     1.支持完整路径搜索 如:http: http://www.baidu.com/img/logo.gif
        ///     2.支持当前网址短路径搜索 如 /img/logo.gif 和 img/logo.gif
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAnalyzeAndDownload_Click(object sender, EventArgs e)
        {
            //ThreadPool 
            //网页路径
            string url = this.tbURL.Text.Trim();
            //保存路径
            string savePath = this.tbSavePath.Text.Trim();

            if (string.IsNullOrEmpty(savePath) || string.IsNullOrEmpty(url))
            {
                MessageBox.Show("保存路径或网址不能为空！！");
                return;
            }

            Match match = Regex.Match(url, URL, RegexOptions.IgnoreCase);
            if (!match.Success)
            {
                MessageBox.Show("网址格式不对！请输入完成的网址，如 http://www.baidu.com ");
                return;
            }

            //初始化全局变量
            init();

            

            //输出路径
            if (!Directory.Exists(savePath))
                Directory.CreateDirectory(savePath);

            

            if (radioButton1.Checked)
                AnalyzeAndDownload(url, savePath);              //同步分析下载
            else
                AsyncAnalyzeAndDownload(url, savePath);         //异步分析下载
        }

        /// <summary>
        /// 初始化全局变量
        /// </summary>
        private void init()
        {

            this.lbShow.Items.Clear();
            //设置状态栏的信息
            SetToolStripStatusLabel("正在分析...", " | 分析耗时:0", " | 共 0 张图片", " | 下载耗时:0", " | 共下载 0 张图片");
            
            //控件不可用
            btnAnalyzeAndDownloadByURI.Enabled = false;
            cbRename.Enabled = false;
            cbDownCss.Enabled = false;

            Application.DoEvents();
        }

        #region 同步分析下载

        /// <summary>
        /// 同步分析下载
        /// </summary>
        private void AnalyzeAndDownload(string url, string savePath)
        {

            #region 计时

            long count = 0;
            long count1 = 0;
            long freq = 0;
            double result = 0;

            QueryPerformanceFrequency(ref freq);
            QueryPerformanceCounter(ref count);

            #endregion

            //需要测试的模块
            List<string> list = URIAnalyze(url);

            #region 计时

            QueryPerformanceCounter(ref count1);
            count = count1 - count;
            result = (double)(count) / (double)freq;

            #endregion

            this.lbShow.Items.AddRange(list.ToArray());
            SetToolStripStatusLabel("分析完毕！正在下载...", string.Format(" | 分析耗时:{0}秒", result), string.Format(" | 共 {0} 张图片", list.Count), string.Empty, string.Empty);
            Application.DoEvents();

            #region 计时

            count = 0;
            count1 = 0;
            freq = 0;
            result = 0;

            QueryPerformanceFrequency(ref freq);
            QueryPerformanceCounter(ref count);

            #endregion

            //下载数据
            DownLoad(list, savePath);

            #region 计时

            QueryPerformanceCounter(ref count1);
            count = count1 - count;
            result = (double)(count) / (double)freq;

            #endregion

            SetToolStripStatusLabel("下载完毕！", string.Empty, string.Empty, string.Format(" | 下载耗时:{0}秒", result), string.Empty);
            btnAnalyzeAndDownloadByURI.Enabled = true;
            cbRename.Enabled = true;
            cbDownCss.Enabled = true;
        }

        /// <summary>
        /// 根据URI分析网站
        /// </summary>
        /// <param name="uriString"></param>
        /// <returns></returns>
        protected List<string> URIAnalyze(string uriString)
        {
            WebClient wClient = null;
            try
            {
                string dnDir = string.Empty;
                string domainName = string.Empty;

                //获得域名 http://www.sina.com/
                Match match = Regex.Match(uriString, DomainPattern, RegexOptions.IgnoreCase);
                domainName = match.Value;

                //获得域名最深层目录 http://www.sina.com/mail/
                if (domainName.Equals(uriString))
                    dnDir = domainName;
                else
                    dnDir = uriString.Substring(0, uriString.LastIndexOf('/'));

                dnDir += '/';

                List<string> list = new List<string>();
                wClient = new WebClient();
                wClient.Credentials = CredentialCache.DefaultCredentials;
                //获得远程服务器返回的数据
                string pageData = Encoding.Default.GetString(wClient.DownloadData(uriString));

                //匹配全路径
                match = Regex.Match(pageData, ImagePattern, RegexOptions.IgnoreCase);

                while (match.Success)
                {
                    string item = match.Value;
                    //短路径处理
                    if (!item.StartsWith("http://") && !item.StartsWith("https://"))
                        item = (item[0] == '/' ? domainName : dnDir) + item;
                    //过滤掉完全一样
                    if (!list.Contains(item))
                        list.Add(item);
                    match = match.NextMatch();
                }
                return list;
            }
            catch (WebException ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                wClient.Dispose();
            }

            return new List<string>();
        }

        /// <summary>
        /// 下载并保存图片
        /// </summary>
        /// <param name="imagesUrlList"></param>
        public void DownLoad(List<string> imagesUrlList, string Dir)
        {
            //判断文件夹是否存在
            if (!Directory.Exists(Dir))
                Directory.CreateDirectory(Dir);

            int i = fileIndex;
            foreach (string item in imagesUrlList)
            {
                try
                {
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create(item);
                    using (Stream stream = hwr.GetResponse().GetResponseStream())
                    {
                        Image img = Image.FromStream(stream);
                        img.Save(Dir + "/" + i.ToString() + item.Substring(item.LastIndexOf('.')));
                        stream.Close();
                        ++i;
                    }
                }
                catch (Exception)
                {
                    //出错继续执行下一个下载
                    continue;
                }
            }
            fileIndex = i;
        }

        #endregion

        #region 异步分析下载

        long count;
        long count1;
        long freq;

        long ccount;
        long ccount1;
        long cfreq;

        int okcount;    //成功下载图片数量

        string uriString;
        string savePath;

        bool isAnalyzeComplete;

        List<string> imgUrlList;



        /// <summary>
        /// 开始异步分析下载
        /// </summary>
        /// <param name="url"></param>
        /// <param name="savePath"></param>
        private void AsyncAnalyzeAndDownload(string url, string savePath)
        {
            uriString = url;
            this.savePath = savePath;

            #region 初始化全局变量

            ccount = 0L;
            ccount1 = 0L;
            cfreq = 0L;

            okcount = 0;

            uriString = string.Empty;
            savePath = string.Empty;

            isAnalyzeComplete = false;

            imgUrlList = new List<string>();

            #endregion

            #region 分析计时开始

            count = 0L;
            count1 = 0L;
            freq = 0L;

            QueryPerformanceFrequency(ref freq);
            QueryPerformanceCounter(ref count);

            #endregion

            using (WebClient wClient = new WebClient())
            {
                AutoResetEvent waiter = new AutoResetEvent(false);
                //为异步结果返回传参
                wClient.QueryString.Add("url", url);
                wClient.QueryString.Add("IsInclueCssImages", _IsInclueCssImages.ToString());
                wClient.Credentials = CredentialCache.DefaultCredentials;
                wClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(AsyncURIAnalyze);
                wClient.DownloadDataAsync(new Uri(url), waiter);
                //waiter.WaitOne();     //阻止当前线程，直到收到信号
            }
        }

        /// <summary>
        /// 异步分析指定网址返回的数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void AsyncURIAnalyze(Object sender, DownloadDataCompletedEventArgs e)
        {
            AutoResetEvent waiter = (AutoResetEvent)e.UserState;
            WebClient nWC = sender as WebClient;
            bool IsMatchCss = true;
            bool IsInclueCssImages = Convert.ToBoolean(nWC.QueryString["IsInclueCssImages"]);
            try
            {
                if (!e.Cancelled && e.Error == null)
                {
                    string dnDir = string.Empty;
                    string domainName = string.Empty;
                    string uri = nWC.QueryString["url"];

                    if (!uri.StartsWith("http://") && !uri.StartsWith("https://"))
                        uri = string.Concat("http://", uri);

                    //获得域名 http://www.sina.com
                    domainName = GetDomain(uri);

                    //获得域名最深层目录 http://www.sina.com/mail/
                    dnDir = GetFullPath(domainName, uri);

                    //获取数据
                    string pageData = Encoding.UTF8.GetString(e.Result);

                    //匹配全路径
                    AnalyzeContent(Regex.Matches(pageData, ImagePattern), domainName, dnDir);

                    //是否下载页面包含CSS文件内的图片
                    if (IsInclueCssImages)
                    {
                        //匹配CSS文件 //[\w=/]*((\.css){1})
                        MatchCollection mc = Regex.Matches(pageData, CssPattern, RegexOptions.IgnoreCase);
                        for (int i = 0, j = mc.Count; i < j; i++)
                        {
                            string item = mc[i].Value;

                            //短路径处理
                            if (!item.StartsWith("http://") && !item.StartsWith("https://"))
                                item = (item[0] == '/' ? domainName : dnDir) + item;

                            using (WebClient wClient = new WebClient())
                            {
                                AutoResetEvent are = new AutoResetEvent(false);
                                wClient.QueryString.Add("url", item);
                                wClient.QueryString.Add("IsOver", i == j - 1 ? "1" : "0");
                                wClient.QueryString.Add("IsInclueCssImages", "false");
                                wClient.Credentials = CredentialCache.DefaultCredentials;
                                wClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(AsyncURIAnalyze);
                                wClient.DownloadDataAsync(new Uri(item), are);
                            }
                        }
                        if (mc.Count == 0)
                            IsMatchCss = false;
                    }
                }
            }
            finally
            {
                //waiter.Set();

                if ((IsInclueCssImages && !IsMatchCss) || (!IsInclueCssImages && string.IsNullOrEmpty(nWC.QueryString["IsOver"])) || (!string.IsNullOrEmpty(nWC.QueryString["IsOver"]) && "1" == nWC.QueryString["IsOver"]))
                {
                    lock (slock)
                    {
                        #region 分析计时结束

                        QueryPerformanceCounter(ref count1);
                        count = count1 - count;
                        
                        toolStripStatusLabel1.Text = "分析完毕！";
                        toolStripStatusLabel2.Text = string.Format(" | 分析耗时:{0:#.####}秒", (double)(count) / (double)freq);

                        #endregion

                        //分析完毕
                        isAnalyzeComplete = true;
                    }
                    Application.DoEvents();
                }
            }
        }

        /// <summary>
        /// 分析链接
        /// </summary>
        /// <param name="mc"></param>
        /// <param name="domainName"></param>
        /// <param name="dnDir"></param>
        private void AnalyzeContent(MatchCollection mc, string domainName, string dnDir)
        {
            List<string> urlList = new List<string>();
            foreach (Match mt in mc)
            {
                string item = mt.Value;

                /*  处理图片正则表达式的缺陷，即图片必须带域名，如:
                 *      当前正则表达式匹配http://www.icoxxx.com
                 *      匹配结果为http://www.ico
                 */
                if (item.Length > 8 && item.IndexOf('/', 9) == -1)
                    continue;

                //短路径处理
                if (!item.StartsWith("http://") && !item.StartsWith("https://"))
                    item = (item[0] == '/' ? domainName : dnDir) + item;

                //处理../
                if (item.IndexOf("../") != -1)
                {
                    List<string> urls = new List<string>();
                    urls.AddRange(item.Split('/'));
                    for (int i = 0; i < urls.Count; i++)
                        if ("..".Equals(urls[i]))
                        {
                            urls.RemoveRange(i - 1, 2);
                            i -= 2;
                        }
                    item = Join("/", urls);
                }

                if (!urlList.Contains(item))
                {
                    urlList.Add(item);

                    lock (slock)
                    {
                        imgUrlList.Add(item);
                    }

                    //实时显示分析结果
                    AddlbShowItem(item);

                    //边分析边下载
                    HttpWebRequest hwr = WebRequest.Create(item) as HttpWebRequest;
                    hwr.AllowWriteStreamBuffering = false;
                    //hwr.ReadWriteTimeout = 5 * 1000; //默认超时30秒
                    IAsyncResult res = hwr.BeginGetResponse(new AsyncCallback(AsyncDownLoad), hwr);
                    //加入线程池控制
                    ThreadPool.RegisterWaitForSingleObject(res.AsyncWaitHandle, new WaitOrTimerCallback(timeoutCallback), hwr, Timeout, true);
                }
            }
        }

        /// <summary>
        /// 线程超时
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="timedOut"></param>
        private static void timeoutCallback(object obj, bool timedOut)
        {
            if (timedOut)
            {
                HttpWebRequest req = (HttpWebRequest)obj;
                if (req != null)
                    req.Abort();
            }
        }


        /// <summary>
        /// 异步接受数据
        /// </summary>
        /// <param name="asyncResult"></param>
        public void AsyncDownLoad(IAsyncResult asyncResult)
        {
            #region 下载计时开始

            lock (slock)
            {
                if (cfreq == 0L)
                {
                    ccount = 0L; 
                    QueryPerformanceFrequency(ref cfreq);
                    QueryPerformanceCounter(ref ccount);
                }
            }

            #endregion
            
            WebRequest request = (WebRequest)asyncResult.AsyncState;
            string url = request.RequestUri.ToString();
            int indexItem = this.lbShow.Items.IndexOf(url);

            //从未下载的列表中删除已经下载的图片
            lock (slock)
            {
                imgUrlList.Remove(url);
            }
            
            try
            {
                WebResponse response = request.EndGetResponse(asyncResult);
                long cLength = response.ContentLength;

                if (cLength > 0 && cLength <= FileSize)
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        Image img = Image.FromStream(stream);
                        img.Save(string.Concat(savePath, "/", GetFileName(url)));
                        img.Dispose();
                        stream.Close();
                    }
                    //allDone.Set();

                    //成功下载
                    if (indexItem >= 0 && indexItem <= this.lbShow.Items.Count)
                        SetlbShowItem(indexItem, "√  ");
                }
                else if (cLength == 0L && indexItem >= 0)
                    SetlbShowItem(indexItem, "×  ");
                else if (indexItem >= 0)
                    SetlbShowItem(indexItem, "!  ");    //表示图片过大或过小
            }
            catch (Exception)
            {
                if (indexItem >= 0)
                    SetlbShowItem(indexItem, "×  ");
            }

        }

        #region 实时显示分析和下载结果

        delegate void SetTextCallback(string text);

        /// <summary>
        ///实时显示分析结果
        /// </summary>
        /// <param name="item"></param>
        private void AddlbShowItem(string item)
        {
            if (this.lbShow.InvokeRequired)
                this.Invoke(new SetTextCallback(AddlbShowItem), new object[] { item });
            else
            {
                this.lbShow.Items.Add(item);
                toolStripStatusLabel3.Text = string.Format(" | 共 {0} 张图片", this.lbShow.Items.Count);
                Application.DoEvents();
            }
        }

        delegate void SetDownloadCallback(int indexItem, string flag);

        /// <summary>
        ///实时显示分析结果
        /// </summary>
        /// <param name="item"></param>
        private void SetlbShowItem(int indexItem, string flag)
        {

            if (this.lbShow.InvokeRequired)
                this.Invoke(new SetDownloadCallback(SetlbShowItem), new object[] { indexItem, flag });
            else
            {
                this.lbShow.Items[indexItem] = string.Concat(flag, this.lbShow.Items[indexItem]);
                if ("√  ".Equals(flag))
                    toolStripStatusLabel5.Text = string.Format(" | 共下载 {0} 张图片", ++okcount);

                if (imgUrlList.Count == 0 && isAnalyzeComplete)
                {
                    #region 下载计时结束

                    QueryPerformanceCounter(ref ccount1);
                    ccount = ccount1 - ccount;

                    #endregion

                    toolStripStatusLabel1.Text = "下载完毕！";
                    toolStripStatusLabel4.Text = string.Format(" | 下载耗时:{0:#.####}秒", (double)(ccount) / (double)cfreq);
                    btnAnalyzeAndDownloadByURI.Enabled = true;
                    cbRename.Enabled = true;
                    cbDownCss.Enabled = true;
                }
                else
                    //是否分析完毕
                    if (isAnalyzeComplete)
                    {
                        if (!"正在下载...".Equals(toolStripStatusLabel1.Text))
                            toolStripStatusLabel1.Text = "正在下载...";
                    }
                    else if (!"正在分析 | 正在下载...".Equals(toolStripStatusLabel1.Text))
                        toolStripStatusLabel1.Text = "正在分析 | 正在下载...";

                Application.DoEvents();
            }
        }

        #endregion

        #endregion

        #region 页面事件

        /// <summary>
        /// 点击打开文件按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender, EventArgs e)
        {
            //选中并确定
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                lbShow.Items.Clear();
                lbShow.Items.AddRange(openFileDialog1.FileNames);
            }
        }

        /// <summary>
        /// 图片保存路径
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            //选中并确定
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                tbSavePath.Text = folderBrowserDialog1.SelectedPath;
            else
                tbSavePath.Text = "";
        }

        /// <summary>
        /// About
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            About about = new About();
            //窗体居中
            about.StartPosition = FormStartPosition.CenterScreen;
            about.Show();
        }

        private void 保存路径SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnSave_Click(sender, e);
        }

        private void 开发文件FToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnOpen_Click(sender, e);
        }

        /// <summary>
        /// 页面加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ImageForm_Load(object sender, EventArgs e)
        {
            //this.MaximumSize = this.MinimumSize;
        }

        /// <summary>
        /// 将选中链接复制到剪切板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbShow_SelectedIndexChanged(object sender, EventArgs e)
        {
            Clipboard.SetText(lbShow.SelectedItem.ToString().Replace("√  ", string.Empty).Replace("×  ", string.Empty).Replace("!  ", string.Empty));
            MessageBox.Show("链接已复制！！欢迎使用笨笨图片下载器 ：）", "复制链接");
        }

        /// <summary>
        /// 文件是否重命名
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBox6_CheckedChanged(object sender, EventArgs e)
        {
            _IsRename = cbRename.Checked;
        }

        /// <summary>
        /// 是否下载页面内包含CSS文件内的图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBox7_CheckedChanged(object sender, EventArgs e)
        {
            _IsInclueCssImages = cbDownCss.Checked;
        }

        private void 初始化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnAnalyzeAndDownloadByURI.Enabled = true;
            cbRename.Enabled = true;
            cbDownCss.Enabled = true;
        }

        #region 配置

        /// <summary>
        /// 设置网址分析正则表达式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入分析网址的正则表达式！！", "更改分析网址的正则表达式", URL, -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsLegalRegex(pattern))
                URL = pattern;
        }

        /// <summary>
        /// 设置图片链接分析正则表达式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 设置图片链接分析正则表达式ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入图片链接分析正则表达式！！", "更改图片链接分析正则表达式", ImagePattern, -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsLegalRegex(pattern))
                ImagePattern = pattern;
        }

        /// <summary>
        /// 设置限制下载文件大
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 设置限制下载文件大小ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入下载文件大小限制（单位KB）！！", "更改下载文件大小限制", Convert.ToString(FileSize / 1024L), -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsInt(pattern))
                FileSize = Convert.ToInt32(pattern) * 1024L;
        }

        /// <summary>
        /// 设置请求超时事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入请求超时事件（单位秒）！！", "更改下载文件大小限制", Convert.ToString(Convert.ToInt32(Timeout) / 1000), -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsInt(pattern))
                Timeout = Convert.ToInt32(pattern) * 1000;
        }

        /// <summary>
        /// 设置域名正则表达式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 设置域名正则表达式ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入域名分析正则表达式！！", "更改域名分析正则表达式", DomainPattern, -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsLegalRegex(pattern))
                DomainPattern = pattern;
        }

        /// <summary>
        /// 正则表达式匹配CSS
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 设置正则表达式匹配CSSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string pattern = Interaction.InputBox("请输入匹配CSS文件正则表达式！！", "更改匹配CSS文件正则表达式", CssPattern, -1, -1);
            if (!string.IsNullOrEmpty(pattern) && CheckIsLegalRegex(pattern))
                CssPattern = pattern;
        }

        #endregion

        #region 重置配置

        /// <summary>
        /// 重置URL
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            URL = URL_BAK;
        }

        /// <summary>
        /// 重置设置限制文件下载大小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            FileSize = FileSize_BAK;
        }

        /// <summary>
        /// 重置图片链接分析正则表达式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem2_Click(object sender, EventArgs e)
        {
            ImagePattern = ImagePattern_BAK;
        }

        /// <summary>
        /// 重置域名分析正则表达式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem3_Click(object sender, EventArgs e)
        {
            DomainPattern = DomainPattern_BAK;
        }

        /// <summary>
        /// 重置请求超时时间
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem4_Click(object sender, EventArgs e)
        {
            Timeout = Timeout_BAK;
        }

        /// <summary>
        /// 重置CSS文件匹配
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 重置ToolStripMenuItem5_Click(object sender, EventArgs e)
        {
            CssPattern = CssPattern_BAK;
        }

        /// <summary>
        /// 全部重置以上设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 全部重置以上设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            URL = URL_BAK;
            FileSize = FileSize_BAK;
            ImagePattern = ImagePattern_BAK;
            DomainPattern = DomainPattern_BAK;
            Timeout = Timeout_BAK;
            CssPattern = CssPattern_BAK;
        }

        #endregion

        #endregion

        #region Tools

        /// <summary>
        /// 判定字符串的末尾是否以集合中任何元素匹配
        /// </summary>
        /// <param name="value"></param>
        /// <param name="collection"></param>
        /// <returns></returns>
        public bool EndsWith(string value, IEnumerable<string> collection)
        {
            foreach (string item in collection)
                if (value.EndsWith(item))
                    return true;
            return false;
        }

        /// <summary>
        /// 增强String.Join，支持ICollection<string>
        /// </summary>
        /// <param name="separator"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public string Join(string separator, ICollection<string> values)
        {
            string[] value = new string[values.Count];
            values.CopyTo(value, 0);
            return String.Join(separator, value);
        }

        /// <summary>
        /// 获得当前url的完整目录
        /// </summary>
        /// <param name="domainName"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        public string GetFullPath(string domainName, string uri)
        {
            return string.Concat(domainName.Equals(uri) ? domainName : uri.Substring(0, uri.LastIndexOf('/')), '/');
        }

        /// <summary>
        /// 获得指定url的domain
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public string GetDomain(string url)
        {
            return Regex.Match(url, DomainPattern).Value;//, RegexOptions.IgnoreCase
        }

        /// <summary>
        /// 获得文件的名称
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public string GetFileName(string url)
        {
            //DateTime.Now.ToString("yyyyMMddHHmmssfff"), new Random().Next(100)
            return _IsRename ? string.Concat(System.Guid.NewGuid(), Path.GetExtension(url)) : Path.GetFileName(url);
        }

        /// <summary>
        /// 设置状态栏的信息
        /// </summary>
        /// <param name="tssl1"></param>
        /// <param name="tssl2"></param>
        /// <param name="tssl3"></param>
        /// <param name="tssl4"></param>
        private void SetToolStripStatusLabel(string tssl1, string tssl2, string tssl3, string tssl4, string tssl5)
        {
            if (!string.IsNullOrEmpty(tssl1))
                toolStripStatusLabel1.Text = tssl1;
            if (!string.IsNullOrEmpty(tssl2))
                toolStripStatusLabel2.Text = tssl2;
            if (!string.IsNullOrEmpty(tssl3))
                toolStripStatusLabel3.Text = tssl3;
            if (!string.IsNullOrEmpty(tssl4))
                toolStripStatusLabel4.Text = tssl4;
            if (!string.IsNullOrEmpty(tssl5))
                toolStripStatusLabel5.Text = tssl5;
        }

        /// <summary>
        /// 验证是否合法的正则表达式
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        private bool CheckIsLegalRegex(string pattern)
        {
            try
            {
                Regex.Match("", pattern);
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("正则表达式不正确！错误信息：\n" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 验证是否是数字
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        private bool CheckIsInt(string pattern)
        {
            return Regex.Match(pattern, @"(\d)*").Success;
        }

        #endregion



        #region 未完成的部分 先注释

        /*
        /// <summary>
        /// 短路径图片搜索
        ///     1.本地已经存在的图片则不拷贝了
        /// </summary>
        /// <returns></returns>
        private List<string> DomainName(string data, string successValue, string uriString)
        {
            List<string> list = new List<string>();

            Match match = Regex.Match(successValue, @"http(s)?://+[\w-.]+/?", RegexOptions.IgnoreCase);
            //获得域名 http://www.sina.com/
            string domainName = string.Empty;
            //是否匹配
            if (match.Success)
            {
                //获得域名最深层目录 http://www.sina.com/mail/
                string dnDir = string.Empty;
                domainName = match.Value;
                match = Regex.Match(successValue, @"http(s)?://[\w-]+\.+[\w-.]+((/?)+[\w-]+/)*", RegexOptions.IgnoreCase);
                dnDir = match.Value;

                //获得文件名
                FileInfo file = new FileInfo(uriString);
                //剪除已经存在的图片
                string dirfilename = file.Name.Substring(0, file.Name.LastIndexOf(".")) + ".files";

                match = Regex.Match(data, @"(((/?)+[\w-.]+/)*)+[\w-]+\.+(jpg|jpeg|bmp|gif|ico)", RegexOptions.IgnoreCase);
                while (match.Success)
                {
                    string item = match.Value;
                    if (!dirfilename.Equals(item))
                    {
                        item = (item[0] == '/' ? domainName : dnDir) + item;
                        //过滤掉完全一样
                        if (!list.Contains(item)) list.Add(item);
                    }
                    match = match.NextMatch();
                }
            }
            return list;
        }


        /// <summary>
        /// 根据文件抓取图片
        /// </summary>
        /// <param name="uriString"></param>
        /// <returns></returns>
        protected List<string> FileAnalyze(string uriString)
        {
            string pageData;
            StreamReader sr = null;
            pageData = string.Empty;

            //取得数据
            try
            {
                sr = new StreamReader(uriString, Encoding.UTF8);
                pageData = sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                ShowWorkingState.Text = string.Format("分析出错！出错文件：[{0}] 错误描述：[{1}]", uriString, ex.Message);
                throw;
            }
            finally
            {
                sr.Close();
            }

            List<string> list = new List<string>();

            //匹配是否有页面的网址
            Match match = Regex.Match(pageData, @"<!-- (saved from url=\(+[\w]+\)|This document saved from )+http(s)?://([\w-]+\.)+[\w-]+((/[\w- ./?%&=]*)?)+[\w_ ]+-->", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                list.AddRange(DomainName(pageData, match.Value, uriString));
            }
            //匹配全路径
            match = Regex.Match(pageData, @"http(s)?://+(((/?)+[\w-.]+(/))*)+[\w-./]+\.+(jpg|jpeg|png|ico|bmp|gif)", RegexOptions.IgnoreCase);

            while (match.Success)
            {
                //过滤掉完全一样
                if (!list.Contains(match.Value)) list.Add(match.Value);
                match = match.NextMatch();
            }

            return list;
        }

        /// <summary>
        /// !!!本方法有待完善，正则表达式在工具里面测试通过，但是这里确通不过！
        /// 根据文件分析并下载
        /// 支持文件格式：*.txt|*.htm|*.html|*.css|*.js|*.mht
        /// 搜索规则：
        ///     1.被搜索的网页文件中如下标示链接，将被模拟成网页地址来处理
        ///         a.<!-- saved from url=(0029)http://www.baidu.com/s?wd=asd -->   //IE
        ///         b.<!-- This document saved from http://www.baidu.com/ -->       //Opera
        ///         //c.火狐好像没有这样的标志
        ///     2.没有如上情况的只找完整链接地址图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAnalyzeAndDownloadByFiles_Click(object sender, EventArgs e)
        {
            //文件地址
            ListBox.ObjectCollection files = lbShow.Items;
            //保存路径
            string savePath = this.tbSavePath.Text.Trim();

            if (string.IsNullOrEmpty(savePath) || files.Count == 0)
            {
                MessageBox.Show("保存路径或待分析的文件列表不能为空！！");
                return;
            }
            //获得文件列表
            string[] fileList = new string[lbShow.Items.Count];
            lbShow.Items.CopyTo(fileList, 0);

            this.lbShow.Items.Clear();
            toolStripStatusLabel1.Text = "正在分析...";
            toolStripStatusLabel2.Text = "分析耗时:0";
            toolStripStatusLabel3.Text = "下载耗时:0";
            toolStripStatusLabel4.Text = "下载耗时:0";
            btnAnalyzeAndDownloadByURI.Enabled = false;
            Application.DoEvents();

            #region 分析

            long count = 0;
            long count1 = 0;
            long freq = 0;
            double result = 0;

            QueryPerformanceFrequency(ref freq);
            QueryPerformanceCounter(ref count);

            //需要测试的模块
            List<string> list = new List<string>();
            foreach (object item in fileList)
            {
                if (File.Exists(item.ToString()))
                {
                    ShowWorkingState.Text = string.Format("正在分析[{0}]。", item);
                    Application.DoEvents();
                    list.AddRange(FileAnalyze(item.ToString()));
                }
                else
                {
                    ShowWorkingState.Text = string.Format("文件[{0}]不存在！", item);
                    Application.DoEvents();
                }
            }

            QueryPerformanceCounter(ref count1);
            count = count1 - count;
            result = (double)(count) / (double)freq;

            #endregion

            this.lbShow.Items.AddRange(list.ToArray());
            toolStripStatusLabel1.Text = "分析完毕正在下载...";
            toolStripStatusLabel2.Text = string.Format("分析耗时:{0}秒", result);
            toolStripStatusLabel3.Text = string.Format("共 {0} 张图片", list.Count);
            Application.DoEvents();

            #region 下载

            count = 0;
            count1 = 0;
            freq = 0;
            result = 0;

            QueryPerformanceFrequency(ref freq);
            QueryPerformanceCounter(ref count);

            //foreach (object var in collection_to_loop)
            //{
            //    if (!Directory.Exists(uriString))
            //    {
            //        MessageBox.Show("文件不存在！！");
            //    }
            //    //下载数据
            //    DownLoad(list, tbSavePath.Text);
            //}

            QueryPerformanceCounter(ref count1);
            count = count1 - count;
            result = (double)(count) / (double)freq;

            #endregion

            toolStripStatusLabel1.Text = "下载完毕!!";
            toolStripStatusLabel4.Text = string.Format("下载耗时:{0}秒", result);
            btnAnalyzeAndDownloadByURI.Enabled = true;
        }
        */

        #endregion

        #region 代码改动备份

        ///// <summary>
        ///// 根据网址分析图片路径
        ///// </summary>
        ///// <param name="pageURL"></param>
        //protected List<string> URIAnalyze(string uriString)
        //{
        //    Match match = Regex.Match(uriString, @"^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.IgnoreCase);
        //    if (match.Success)
        //    {
        //        WebClient wClient = null;
        //        try
        //        {
        //            string dnDir = string.Empty;
        //            string domainName = string.Empty;

        //            //获得域名最深层目录 http://www.sina.com/mail/
        //            dnDir = uriString.Substring(0, uriString.LastIndexOf('/') + 1);
        //            //获得域名 http://www.sina.com/
        //            match = Regex.Match(uriString, @"http(s)?://+[\w-.]+[^/]", RegexOptions.IgnoreCase);
        //            domainName = match.Value;

        //            List<string> list = new List<string>();
        //            wClient = new WebClient();
        //            wClient.Credentials = CredentialCache.DefaultCredentials;
        //            //获得远程服务器返回的数据
        //            string pageData = Encoding.Default.GetString(wClient.DownloadData(uriString));

        //            //匹配全路径
        //            match = Regex.Match(pageData, @"((http(s)?://)?)+(((/?)+[\w-.]+(/))*)+[\w-./]+\.+(" + ImageType + ")", RegexOptions.IgnoreCase);

        //            while (match.Success)
        //            {
        //                string item = match.Value;
        //                //短路径处理
        //                if (item.IndexOf("http://") == -1 && item.IndexOf("https://") == -1)
        //                    item = (item[0] == '/' ? domainName : dnDir) + item;
        //                //过滤掉完全一样
        //                if (!list.Contains(item))
        //                    list.Add(item);
        //                match = match.NextMatch();
        //            }
        //            return list;
        //        }
        //        catch (WebException ex)
        //        {
        //            MessageBox.Show(ex.Message);
        //        }
        //        finally
        //        {
        //            wClient.Dispose();
        //        }
        //    }
        //    return new List<string>();
        //}

        //private void btnTest_Click(object sender, EventArgs e)
        //{
        //    Match match = Regex.Match("", @"(((/?)+[\w-.]+/)*)+[\w-]+\.+(jpg|jpeg|bmp|gif|ico)", RegexOptions.IgnoreCase);
        //}

        ///// <summary>
        ///// 异步分析
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //protected void AsyncURIAnalyze(Object sender, DownloadDataCompletedEventArgs e)
        //{
        //    AutoResetEvent waiter = (AutoResetEvent)e.UserState;
        //    try
        //    {
        //        if (!e.Cancelled && e.Error == null)
        //        {

        //            string dnDir = string.Empty;
        //            string domainName = string.Empty;
        //            string uri = uriString;

        //            //判断是否以[http://]或[https://]开头的网址

        //            if (!uri.StartsWith("http://") && !uri.StartsWith("https://"))
        //                uri = string.Concat("http://", uri);

        //            //获得域名 http://www.sina.com/
        //            Match match = Regex.Match(uri, DomainPattern);//, RegexOptions.IgnoreCase
        //            domainName = match.Value;

        //            //获得域名最深层目录 http://www.sina.com/mail/
        //            if (domainName.Equals(uri))
        //                dnDir = domainName;
        //            else
        //                dnDir = uri.Substring(0, uri.LastIndexOf('/'));

        //            dnDir += '/';

        //            //获取数据
        //            string pageData = Encoding.UTF8.GetString(e.Result);
        //            List<string> urlList = new List<string>();

        //            //匹配全路径
        //            MatchCollection mc = Regex.Matches(pageData, ImagePattern);
        //            foreach (Match mt in mc)
        //            {
        //                string item = mt.Value;
        //                //短路径处理
        //                if (!item.StartsWith("http://") && !item.StartsWith("https://"))
        //                    item = (item[0] == '/' ? domainName : dnDir) + item;

        //                if (!urlList.Contains(item))
        //                {
        //                    urlList.Add(item);
        //                    imgUrlList.Add(item);

        //                    //实时显示分析结果
        //                    AddlbShowItem(item);

        //                    //边分析边下载
        //                    HttpWebRequest hwr = WebRequest.Create(item) as HttpWebRequest;
        //                    //测试看看对文件大小管不管用
        //                    hwr.MaximumResponseHeadersLength = FileSize; //KB
        //                    hwr.AllowWriteStreamBuffering = false;
        //                    hwr.ReadWriteTimeout = 0x493E0; //默认超时30秒
        //                    hwr.BeginGetResponse(new AsyncCallback(AsyncDownLoad), hwr);
        //                    //hwr.Timeout = "0x30D40";        //默认 0x186a0 -> 100000 0x30D40 -> 200000
        //                    //hwr.Method = "POST";
        //                    //hwr.ContentType = "application/x-www-form-urlencoded";
        //                    //hwr.MaximumAutomaticRedirections = 3;
        //                    //hwr.Accept ="image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
        //                    //hwr.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
        //                    //IAsyncResult iar = hwr.BeginGetResponse(new AsyncCallback(AsyncDownLoad), hwr);
        //                    //iar.AsyncWaitHandle.WaitOne();
        //                }
        //            }
        //            //while (match.Success)
        //            //{

        //            //    match = match.NextMatch();
        //            //}
        //        }
        //    }
        //    finally
        //    {
        //        waiter.Set();

        //        #region 分析计时结束

        //        QueryPerformanceCounter(ref count1);
        //        count = count1 - count;
        //        result = (double)(count) / (double)freq;

        //        toolStripStatusLabel1.Text = "分析完毕！";
        //        toolStripStatusLabel2.Text = string.Format(" | 分析耗时:{0}秒", result);
        //        Application.DoEvents();

        //        #endregion

        //        //分析完毕
        //        isAnalyzeComplete = true;
        //    }
        //}

        #endregion

        #region 废弃的代码

        //private List<string> _ImageType = new List<string>();
        ///// <summary>
        ///// 下载图片类型 
        ///// </summary>
        //public List<string> ImageType
        //{
        //    get
        //    {
        //        if (_ImageType.Count == 0)
        //            _ImageType.AddRange(new string[] { ".jpg", ".jpeg", ".png", ".ico", ".bmp", ".gif" });
        //        return _ImageType;
        //    }
        //}

        //public delegate void AsyncEventHandler();

        ///// <summary>
        ///// gif图片格式
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void ch_ImageType3_CheckedChanged(object sender, EventArgs e)
        //{
        //    CheckImagesType(ch_ImageType3);
        //}

        ///// <summary>
        ///// bmp图片格式
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void ch_ImageType2_CheckedChanged(object sender, EventArgs e)
        //{
        //    CheckImagesType(ch_ImageType2);
        //}

        ///// <summary>
        ///// jpg|jpeg图片格式
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void ch_ImageType1_CheckedChanged(object sender, EventArgs e)
        //{
        //    CheckImagesType(ch_ImageType1);


        //}

        ///// <summary>
        ///// ico图片格式
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void ch_ImageType4_CheckedChanged(object sender, EventArgs e)
        //{
        //    CheckImagesType(ch_ImageType4);
        //}

        //private string _ImageType = "jpg|jpeg|png|ico|bmp|gif";
        ///// <summary>
        ///// 下载图片类型 
        ///// </summary>
        //public string ImageType
        //{
        //    get
        //    {
        //        return _ImageType;
        //    }
        //    set
        //    {
        //        _ImageType = value;
        //    }
        //}

        ///// <summary>
        ///// 获得图片类型
        ///// </summary>
        ///// <returns></returns>
        //private void CheckImagesType(CheckBox cbox)
        //{
        //    string ImageType = _ImageType + '|';

        //    ImageType = cbox.Checked ? string.Concat(ImageType, cbox.Text) : ImageType.Replace(cbox.Text + '|', string.Empty);

        //    if ('|'.Equals(ImageType[ImageType.Length - 1]))
        //        ImageType = ImageType.Remove(ImageType.Length - 1, 1);

        //    _ImageType = ImageType;
        //}

        #endregion
    }
}